package net.tngou.iask.action.api;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.math.NumberUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baidu.ueditor.ActionEnter;

import net.tngou.iask.action.BaseAction;
import net.tngou.iask.pojo.Patient;
import net.tngou.iask.util.ImgTool;
import net.tngou.iask.util.StringUtil;



/**
 * 上传文件
 * @author tngou@tngou.net
 * action=uploadfile 文件
 * action=uploadimage 图片
 *
 */
public class UploadApi extends BaseAction {
	
	private String propath;


	/**
	 * 百度 UEditor 删除
	 */
	@Override
	public void execute() throws ServletException, IOException {
		String rootPath= request.getServletContext().getRealPath(request.getContextPath());
		printJson(new ActionEnter( request,rootPath).exec()); 
	}
	
	
	/**
	 * 百度  WebuPloader上传
	 */
	public void webuploader() {
		if(user==null){
			run_error(500, "没有上传权限");return;
		}
		if(ask.getId()==0)
		{
			run_error(500, "请求参数不正确！");return;
		}
		Patient patient = new Patient().get(ask.getId());
		if(patient==null)
		{
			run_error(500, "请求数据不正确！");return;
		}
		 try {
	            //String path = 
	            boolean isMultipart = ServletFileUpload.isMultipartContent(request);
	 
	            if (isMultipart) {
	                FileItemFactory factory = new DiskFileItemFactory();
	                ServletFileUpload upload = new ServletFileUpload(factory);
	 
	                // 得到所有的表单域，它们目前都被当作FileItem
	                List<FileItem> fileItems = upload.parseRequest(request);
	 
	                String id = "";
	                String fileName = "";
	                // 如果大于1说明是分片处理
	                int chunks = 1;
	                int chunk = 0;
	                FileItem tempFileItem = null;
	 
	                for (FileItem fileItem : fileItems) {
	                    if (fileItem.getFieldName().equals("id")) {
	                        id = fileItem.getString();
	                    } else if (fileItem.getFieldName().equals("name")) {
	                        fileName = new String(fileItem.getString().getBytes(
	                                "ISO-8859-1"), "UTF-8");
	                    } else if (fileItem.getFieldName().equals("chunks")) {
	                        chunks = NumberUtils.toInt(fileItem.getString());
	                    } else if (fileItem.getFieldName().equals("chunk")) {
	                        chunk = NumberUtils.toInt(fileItem.getString());
	                    } else if (fileItem.getFieldName().equals("file")) {
	                        tempFileItem = fileItem;
	                    }
	                }
	 
	                // 临时目录用来存放所有分片文件
	                String tempFileDir = getTempFilePath(user.getMain(),patient.getId())
	                        + File.separator + id;
	                File parentFileDir = new File(tempFileDir);
	                if (!parentFileDir.exists()) {
	                    parentFileDir.mkdirs();
	                }
	                // 分片处理时，前台会多次调用上传接口，每次都会上传文件的一部分到后台(默认每片为5M)
	                File tempPartFile = new File(parentFileDir, fileName + "_" + chunk
	                        + ".part");
	                FileUtils.copyInputStreamToFile(tempFileItem.getInputStream(),
	                        tempPartFile);
	 
	                // 是否全部上传完成
	                // 所有分片都存在才说明整个文件上传完成
	                boolean uploadDone = true;
	                for (int i = 0; i < chunks; i++) {
	                    File partFile = new File(parentFileDir, fileName + "_" + i
	                            + ".part");
	                    if (!partFile.exists()) {
	                        uploadDone = false;
	                    }
	                }
	                // 所有分片文件都上传完成
	                // 将所有分片文件合并到一个文件中
	                if (uploadDone) {
	                    File destTempFile = new File(getTempFilePath(user.getMain(),patient.getId()), fileName);
	                   // System.err.println(destTempFile.getPath());
	                    for (int i = 0; i < chunks; i++) {
	                        File partFile = new File(parentFileDir, fileName + "_"
	                                + i + ".part");
	 
	                        FileOutputStream destTempfos = new FileOutputStream(
	                                destTempFile, true);
	                        
	                        FileUtils.copyFile(partFile, destTempfos);
	 
	                        destTempfos.close();
	                    }
	                    // 得到 destTempFile 就是最终的文件
	                    // 添加到文件系统或者存储中	                     
	                    // 删除临时目录中的分片文件
	                    FileUtils.deleteDirectory(parentFileDir);
	                    // 删除临时文件
	                   // destTempFile.delete();
	                     
	                    run_ok();
	                } else {
	                    // 临时文件创建失败
	                    if (chunk == chunks -1) {
	                        FileUtils.deleteDirectory(parentFileDir);
	                        run_error(500, "内部错误");
	                    }
	                }
	            }
	        } catch (Exception e) {
	            
	        	run_error(500, "内部错误");
	        }
	}
	

	
	/**
	 * 百度 ufinder
	 * @throws IOException
	 */
	public void ufinder() throws IOException {
		
		if(user==null){
			printHtml(getJson("1", "没有上传权限", null));return;
		}
		if(ask.getId()==0)
		{
			printHtml(getJson("1", "请求参数不正确", null));return;
		}
		Patient patient = new Patient().get(ask.getId());
		if(patient==null)
		{

			printHtml(getJson("1", "请求数据不正确！", null));return;
		}
		propath=getTempFilePath(user.getMain(), patient.getId());
		request.setCharacterEncoding("UTF-8");
		String ROOT = "";
		String cmd = request.getParameter("cmd"); // $_GET["cmd"];
		String target = request.getParameter("target"); // $target =
														// $_GET["target"]; 

		String array[] = { ".gif", ".png", ".jpg", ".jpeg", ".bmp" };
		Map<String, Object> uploadconfig = new HashMap<String, Object>();
		uploadconfig.put("savePath", "upload/");
		uploadconfig.put("maxSize", 1000);
		uploadconfig.put("allowFiles", array);
		Map<String, Object> sysconfig = new HashMap<String, Object>(); 
		sysconfig.put("ROOT", "/annex");
		sysconfig.put("write", true);
		sysconfig.put("read", true);
		sysconfig.put("upload", uploadconfig);
		
		Map<String, Object> mapconfig = new HashMap<String, Object>();
		
		Map<String, Object> map = new HashMap<String, Object>(); 
 
		if (cmd.equals("init")) { //初始化
			map.put("root", getFileInfo("/", ROOT));
			map.put("config", mapconfig);
			printHtml(getJson("0", "success", map));
		} else if (cmd.equals("ls")) {//文件列表
			if (null != target && !target.equals(""))
				;
			else
				target = "";
			List<Map<String, Object>> list = listFile(target, ROOT); 
			map.put("files", list);
			printHtml(getJson("0", "success", map));
		} else if (cmd.equals("rename")) {//重命名
			String name = request.getParameter("name");
			Boolean flag = rename(ROOT + target, ROOT + name); 
			map.put("file", getFileInfo(name, ROOT));
			if (flag) {
				printHtml(getJson("0", "success", map));
			} else {
				printHtml(getJson("1", "rename error", null));
			}

		} else if (cmd.equals("rm")) {//删除
			Boolean flag = false;
			String[] targets = request.getParameterValues("target[]");
			for (int i = 0; i < targets.length; i++) {
				flag = remove(targets[i], ROOT);
				if (!flag) {
					break;
				}
			}

			if (flag) {
				printHtml(getJson("0", "success", null));
			} else {
				printHtml(getJson("1", "rename error", null));
			}

		} else if (cmd.equals("touch")) {//新建文件
			Boolean flag = file_put_contents(target, ROOT);
			if (flag) { 
				map.put("file", getFileInfo(target, ROOT));
				printHtml(getJson("0", "success", map));
			} else {
				printHtml(getJson("1", "touch error", null));
			}

		} else if (cmd.equals("mkdir")) {//新建目录
			Boolean res = mkdir(ROOT, target); 
			map.put("file", getFileInfo(target, ROOT));
			if (res) {
				printHtml(getJson("0", "success", map));
			} else {
				printHtml(getJson("1", "error", map));
			}

		} else if (cmd.equals("upload")) {//上传：目前可能因ufinder还有问题
		
			String filename = uploadfile( target, ROOT); 
			map.put("file", getFileInfo(target + filename, ROOT));
			if (filename.length() > 0) {
				System.out.print(getJson("0", "success", map));
				printHtml(getJson("0", "success", map));
			} else {
				printHtml(getJson("1", "fail", map));
			}
			
			
		} else if (cmd.equals("download")) {//下载
			download(request, response, target, user.getMain(),patient.getId());
		} else if (cmd.equals("info")) { 
			map.put("file", getFileInfo(target, ROOT));
			printHtml(getJson("0", "success", map));
		} else {
			printHtml(getJson("1", "unknow command", null));
}
	}
	
	private String uploadfile(String target, String root) {
		try {
            //String path = 
            boolean isMultipart = ServletFileUpload.isMultipartContent(request);
 
            if (isMultipart) {
                FileItemFactory factory = new DiskFileItemFactory();
                ServletFileUpload upload = new ServletFileUpload(factory);
 
                // 得到所有的表单域，它们目前都被当作FileItem
                List<FileItem> fileItems = upload.parseRequest(request);
 
                String id = "";
                String fileName = "";
                // 如果大于1说明是分片处理
                int chunks = 1;
                int chunk = 0;
                FileItem tempFileItem = null;
 
                for (FileItem fileItem : fileItems) {
                    if (fileItem.getFieldName().equals("id")) {
                        id = fileItem.getString();
                    } else if (fileItem.getFieldName().equals("name")) {
                        fileName = new String(fileItem.getString().getBytes(
                                "ISO-8859-1"), "UTF-8");
                    } else if (fileItem.getFieldName().equals("chunks")) {
                        chunks = NumberUtils.toInt(fileItem.getString());
                    } else if (fileItem.getFieldName().equals("chunk")) {
                        chunk = NumberUtils.toInt(fileItem.getString());
                    } else if (fileItem.getFieldName().equals("file")) {
                        tempFileItem = fileItem;
                    }
                }
 
                // 临时目录用来存放所有分片文件
                String tempFileDir =propath +  root+target
                        + File.separator + id;
                File parentFileDir = new File(tempFileDir);
                if (!parentFileDir.exists()) {
                    parentFileDir.mkdirs();
                }
                // 分片处理时，前台会多次调用上传接口，每次都会上传文件的一部分到后台(默认每片为5M)
                File tempPartFile = new File(parentFileDir, fileName + "_" + chunk
                        + ".part");
                FileUtils.copyInputStreamToFile(tempFileItem.getInputStream(),
                        tempPartFile);
 
                // 是否全部上传完成
                // 所有分片都存在才说明整个文件上传完成
                boolean uploadDone = true;
                for (int i = 0; i < chunks; i++) {
                    File partFile = new File(parentFileDir, fileName + "_" + i
                            + ".part");
                    if (!partFile.exists()) {
                        uploadDone = false;
                    }
                }
                // 所有分片文件都上传完成
                // 将所有分片文件合并到一个文件中
                if (uploadDone) {
                    File destTempFile = new File(propath + root+target, fileName);
                   // System.err.println(destTempFile.getPath());
                    for (int i = 0; i < chunks; i++) {
                        File partFile = new File(parentFileDir, fileName + "_"
                                + i + ".part");
 
                        FileOutputStream destTempfos = new FileOutputStream(
                                destTempFile, true);
                        
                        FileUtils.copyFile(partFile, destTempfos);
 
                        destTempfos.close();
                    }
                    // 得到 destTempFile 就是最终的文件
                    // 添加到文件系统或者存储中	                     
                    // 删除临时目录中的分片文件
                    FileUtils.deleteDirectory(parentFileDir);
                    // 删除临时文件
                   // destTempFile.delete();
                     return fileName;
                   
                } else {
                    // 临时文件创建失败
                    if (chunk == chunks -1) {
                        FileUtils.deleteDirectory(parentFileDir);    
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        	
        }
		  return "";
	}


	private void run_error(int code,String message) {
		JSONObject json = new JSONObject();
		json.put("jsonrpc", "2.0");
		JSONObject error = new JSONObject();
		error.put("code", code);
		error.put("message", message);
		json.put("error", error);
		json.put("id", "id");
		printJson(json.toJSONString());
	}
	private void run_ok() {
		JSONObject json = new JSONObject();
		json.put("jsonrpc", "2.0");
		json.put("result", "null");
		json.put("id", "id");
		printJson(json.toJSONString());
	}
	
	private String getTempFilePath(long main,long patient) {
		return request.getServletContext().getRealPath("")+File.separator+"annex"+File.separator+main+File.separator+patient;
	}
	public String getFileName(String path) {
		int index = path.lastIndexOf("/");
		if (index != -1) {
			return path.substring(index);
		} else {
			return path;
		}
	}

	public String getJson(String state, String message, Map<String, Object> data) {
		Map<String, Object> jsonmap = new HashMap<String, Object>();
		jsonmap.put("state", state);
		jsonmap.put("message", message);

		if (data != null)
			jsonmap.put("data", data);

		JSONObject json = (JSONObject) JSON.toJSON(jsonmap);
		return json.toJSONString();
	}

	public List<Map<String, Object>> listFile(String dirpath, String ROOT)
	{
		String ROOTPATH =propath + ROOT;
		System.err.println(ROOTPATH);
		File dir = new File(ROOTPATH + dirpath);
		File[] files = dir.listFiles();
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		if (null != files) {
			for (int i = 0; i < files.length; i++) {
			
				list.add(getFileInfo( files[i].getPath().substring(propath.length()),
						ROOT));
			}
		}
		return list;
	}
	public Map<String, Object> getFileInfo(String path, String root) {
		String rootpath =propath + root + path; 
		String regexp = "\\\\";
		path = path.replaceAll(regexp, "/");

		File file = new File(rootpath);
		Map<String, Object> info = new HashMap<String, Object>();
		if (path.lastIndexOf(".") != -1 || path.equals("/")) {
			info.put("path", path);
		} else {
			info.put("path", path + "/");
		}
		info.put("name", file.getName());
		info.put("isdir", file.isDirectory());
		if (path.lastIndexOf(".") != -1)
			info.put("type", "file");
		else {
			info.put("type", "dir");
		}
		info.put("read", file.canRead());
		info.put("write", file.canWrite());
		info.put("time", file.lastModified());
		// info.put("mode",);
		info.put("size", file.length());
		return info;

	}

	public Boolean rename(String oldname, String newname) {
		String oldpath = propath + oldname;
		String newpath = propath + newname;
		File oldfile = new File(oldpath); // 指定文件名及路径
		File newfile = new File(newpath);
		if (newfile.exists()) {
			return false;
		} else {
			oldfile.renameTo(newfile); // 改名
			return true;
		}

	}

	public Boolean file_put_contents(String target, String ROOT)
			throws IOException {
		String rootpath = propath + ROOT + target;
		File file = new File(rootpath);
		if (!file.exists()) {
			file.createNewFile();
			return true;
		} else {
			return false;
		}
	}

	public Boolean mkdir(String ROOT, String path) {
		String rootpath = propath + ROOT + path;
		File file = new File(rootpath);
		if (!file.exists()) {
			file.mkdir();
			return true;
		}
		return false;
	}

	/**
	 * 删除空目录
	 * 
	 * @param dir
	 *            将要删除的目录路径
	 */
	public void doDeleteEmptyDir(String dir) {
		boolean success = (new File(dir)).delete();
		if (success) {
			System.out.println("Successfully deleted empty directory: " + dir);
		} else {
			System.out.println("Failed to delete empty directory: " + dir);
		}
	}

	/**
	 * 递归删除目录下的所有文件及子目录下所有文件
	 * 
	 * @param dir
	 *            将要删除的文件目录
	 * @return boolean Returns "true" if all deletions were successful. If a
	 *         deletion fails, the method stops attempting to delete and returns
	 *         "false".
	 */
	public boolean deleteDir(File dir) {
		if (dir.isDirectory()) {
			String[] children = dir.list();
			for (int i = 0; i < children.length; i++) {
				boolean success = deleteDir(new File(dir, children[i]));
				if (!success) {
					return false;
				}
			}
		}
		// 目录此时为空，可以删除
		return dir.delete();
	}

	public Boolean remove(String target, String ROOT) {
		String ROOTPATH = propath + ROOT;
		File dir = new File(ROOTPATH + target);
		boolean success = deleteDir(dir);
		// doDeleteEmptyDir(ROOTPATH);
		return true;
	}

	
	public void download(HttpServletRequest req, HttpServletResponse resp,
			String target, long main,long patient) throws IOException { 
        String fullFilePath = getTempFilePath(main, patient);

        /*读取文件*/

        File file = new File(fullFilePath,target);

        /*如果文件存在*/

        if (file.exists()) {

            String filename = URLEncoder.encode(file.getName(), "UTF-8");

            resp.reset();

            resp.setContentType("application/x-msdownload");

            resp.addHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");

            int fileLength = (int) file.length();

            resp.setContentLength(fileLength);

           /*如果文件长度大于0*/

            if (fileLength != 0) {

                /*创建输入流*/

                InputStream inStream = new FileInputStream(file);

                byte[] buf = new byte[4096];

                /*创建输出流*/

                ServletOutputStream servletOS = resp.getOutputStream();

                int readLength;

                while (((readLength = inStream.read(buf)) != -1)) {

                    servletOS.write(buf, 0, readLength);

                }

                inStream.close();

                servletOS.flush();

                servletOS.close();

            }

        }
	}
	
}
